// GummyBear ^_^
// sqlParser.cpp

#include <iostream>
#include <string>
#include <sstream>

#include "sqlParser.h"

void sqlParser::Illegal() {
  std::cout << "Your command isn't legal. Check and enter it again." << std::endl;
}

command* sqlParser::excecute(std::string strcommand) {
  // Transfer to lower letters.
  for (int i = 0; i < (int)strcommand.size(); i++) 
    strcommand[i] = tolower(strcommand[i]);
  command* result = nullptr;

  // Use stringstream to splict the sentence.
  std::istringstream splitStream(strcommand);
  std::string singleWord;

  // Read the first word--keyWord.
  splitStream >> singleWord;

  // For "CREATE", it devides into "create database" and "create table"
  if (!singleWord.compare("create")) {
    
    // Build a command;
    result = new command(singleWord);

    splitStream >> singleWord;

    // "create database"
    if (!singleWord.compare("database")) {
      // Save object type;
      result->obj = singleWord;

      // Save object name;
      splitStream >> singleWord;
      result->objName = singleWord;

      // Return;
      return result;
    } else

    // "create table"
    if (!singleWord.compare("table")) {
      // Save object type;
      result->obj = singleWord;

      // Save object name;
      splitStream >> singleWord;
      if (singleWord[singleWord.length() - 1] == '(')
        result->objName = singleWord.substr(0, singleWord.length() - 1);
      else result->objName = singleWord;

      // Read table message.
      std::string message;
      // Build the titleDlistHead;
      result->titleHead = (titleNode*)malloc(sizeof(titleNode));
      titleNode *head = result->titleHead;
      while (true) {

        std::getline(std::cin, message);
        for (int i = 0; i < (int)message.size(); i++) 
          message[i] = tolower(message[i]);
        splitStream.clear();
        splitStream.str(message);

        // The first statement: <column-name> or ')';
        splitStream >> singleWord;
        if (!singleWord.compare(")")) break;

        // New node init.
        titleNode *newColumn;
        newColumn = (titleNode*)malloc(sizeof(titleNode));
        newColumn->next = nullptr;
        newColumn->titleName = singleWord;
        newColumn->isPrimary = false;

        //The second statement: <column-data-type>; But maybe end up with ",";
        splitStream >> singleWord;
        if(singleWord[singleWord.length() - 1] == ',') {
          std::string transfer = singleWord.substr(0, singleWord.length() - 1);
          newColumn->titleType = transfer;
          if (!newColumn->titleType.compare("char")) newColumn->strPtr = (std::string*)malloc(sizeof(std::string) * defaultLength);
            else newColumn->intPtr = (int*)malloc(sizeof(int) * defaultLength);
        } else{
          newColumn->titleType = singleWord;
          if (!newColumn->titleType.compare("char")) newColumn->strPtr = (std::string*)malloc(sizeof(std::string) * defaultLength);
            else newColumn->intPtr = (int*)malloc(sizeof(int) * defaultLength);

          // The third statement: Is primary?
          if (splitStream >> singleWord) newColumn->isPrimary = true;
        }
        // Add it to the dlist.
        head->next = newColumn;
        head = head->next;
      } 
      return result;
    }
  }

  // For 'drop', it also has 'drop database' and 'drop table';
  if (!singleWord.compare("drop")) {

    // Build a command;
    result = new command(singleWord);

    splitStream >> singleWord;

    // "drop database" and "drop table"
    if ((!singleWord.compare("database")) || (!singleWord.compare("table"))) {
      // Save object type;
      result->obj = singleWord;

      // Save object name;
      splitStream >> singleWord;
      result->objName = singleWord;

      // Return;
      return result;
    }
  }

  // Parse "use"
  if (!singleWord.compare("use")) {
    
    // Build a command;
    result = new command(singleWord);

    result->keyWord = singleWord;
    result->obj = "database";

    splitStream >> singleWord;
    result->objName = singleWord;

    return result;
  }


  if (!singleWord.compare("select")) {
    //Todo

    return result;
  }

  // Insert ...
  if (!singleWord.compare("insert")) {
    result = new command(singleWord);

    result->obj = "table";
    splitStream >> singleWord;
    result->objName = singleWord;
    splitStream >> singleWord;
    while(splitStream >> singleWord) {
      result->insertValue += singleWord;
      result->insertValue += " ";
    }

    return result;
  }

  if (!singleWord.compare("delete")) {
    //Todo

    return result;
  }

  Illegal();
  if (result != nullptr) 
    result = nullptr; 
  
  return result;
}